
from util.client_cosmic import console, Cosmic
import numpy as np 
import sounddevice as sd
import asyncio
import sys
import time
from rich import inspect
import threading


def record_callback(indata: np.ndarray, 
                    frames: int,
                    time_info,
                    status: sd.CallbackFlags) -> None:
    if not Cosmic.on:
        return
    asyncio.run_coroutine_threadsafe(
        Cosmic.queue_in.put(
            {'type': 'data',
             'time': time.time(),
             'data': indata.copy(),
             },
        ),
        Cosmic.loop
    )


def stream_close(signum, frame):
    Cosmic.stream.close()

def stream_reopen():
    if not threading.main_thread().is_alive():
        return

    # 添加重启计数器，防止无限重启
    if not hasattr(Cosmic, 'restart_count'):
        Cosmic.restart_count = 0

    Cosmic.restart_count += 1
    if Cosmic.restart_count > 5:
        console.print('音频流重启次数过多，停止自动重启', style='bright_red')
        return

    print(f'重启音频流 (第{Cosmic.restart_count}次)')

    try:
        # 关闭旧流
        if hasattr(Cosmic, 'stream') and Cosmic.stream:
            Cosmic.stream.close()

        # 重载 PortAudio，更新设备列表
        sd._terminate()
        sd._ffi.dlclose(sd._lib)
        sd._lib = sd._ffi.dlopen(sd._libname)
        sd._initialize()

        # 打开新流
        time.sleep(0.5)  # 增加等待时间
        Cosmic.stream = stream_open()

        # 重启成功，重置计数器
        Cosmic.restart_count = 0

    except Exception as e:
        console.print(f'音频流重启失败: {e}', style='bright_red')
        if Cosmic.restart_count >= 5:
            console.print('请检查音频设备连接或重启程序', style='bright_red')


def stream_open():
    # 显示录音所用的音频设备
    channels = 1
    try:
        device = sd.query_devices(kind='input')
        channels = min(2, device['max_input_channels'])
        # 处理设备名称的编码问题
        device_name = device["name"]
        try:
            # 尝试编码到GBK，如果失败则使用安全的替换
            device_name.encode('gbk')
        except UnicodeEncodeError:
            # 如果包含无法编码的字符，使用简化显示
            device_name = "默认音频设备"
        console.print(f'使用默认音频设备：[italic]{device_name}，声道数：{channels}', end='\n\n')
    except UnicodeDecodeError:
        console.print("由于编码问题，暂时无法获得麦克风设备名字", end='\n\n', style='bright_red')
    except Exception as e:
        console.print(f"音频设备初始化失败：{str(e)}", end='\n\n', style='bright_red')
    except sd.PortAudioError:
        console.print("没有找到麦克风设备", end='\n\n', style='bright_red')
        input('按回车键退出'); sys.exit()

    stream = sd.InputStream(
        samplerate=48000,
        blocksize=int(0.05 * 48000),  # 0.05 seconds
        device=None,
        dtype="float32",
        channels=channels,
        callback=record_callback,
        finished_callback=stream_reopen,
    ); stream.start()

    return stream

